import 'package:sow_app/repository/model/book_comment_model.dart';
import 'package:sow_app_core/sow_app_core.dart';
import 'package:sow_app_i18n/sow_app_i18n.dart';

import 'model/book_classify_model.dart';
import 'model/book_shelf_model.dart';
import 'model/chapter_model.dart';
import 'model/novel_model.dart';

class AjaxNovelRepository extends NovelRepository {
  final RestClient client;

  AjaxNovelRepository(this.client);

  @override
  Future<Novel> novelDetail(String novelId) async {
    var path = 'book/queryBookDetail/$novelId';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, type);
    var classifyPath = 'book/queryBookCategory/$novelId';

    final classifyResponse = await client.invokeHttp(classifyPath, type);
    response.data["catList"] = classifyResponse.data;
    return NovelModel.fromJson(response.data).toEntity();
  }

  @override
  Future<List<Novel>> novelList(String? title) async {
    const path = 'book/searchByPage';

    RequestType type = RequestType.get;
    final response =
        await client.invokeHttp(path, body: {'keyword': title}, type);

    return (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();
  }

  @override
  Future<void> novelSubscribe(String novelId) async {
    var path = 'user/addToBookShelf';

    RequestType type = RequestType.post;
    await client.invokeHttp(path, type, body: {'bookId': novelId});
  }

  @override
  Future<void> novelUnsubscribe(String novelId) async {
    var path = 'user/removeFromBookShelf/$novelId';

    RequestType type = RequestType.delete;
    await client.invokeHttp(path, type);
  }

  @override
  Future<bool> novelIsSubscribe(String novelId) async {
    const path = 'user/queryIsInShelf';

    RequestType type = RequestType.get;
    final response =
        await client.invokeHttp(path, body: {"bookId": novelId}, type);
    return response.data;
  }

  @override
  Future<List<NovelComment>> getBookCommentList(String params) async {
    const path = 'book/listCommentByPage';

    RequestType type = RequestType.get;
    final response =
        await client.invokeHttp(path, body: {"bookId": params}, type);
    return (response.data['list'] as List)
        .map<NovelComment>((e) => BookCommentModel.fromJson(e).toEntity())
        .toList();
  }

  @override
  Future<void> addBookComment(NovelComment params) async {
    const path = 'book/addBookComment';

    RequestType type = RequestType.post;
    await client.invokeHttp(
        path,
        body: {
          'bookId': params.bookId,
          'commentContent': params.content,
        },
        type);
  }

  @override
  Future<List<Novel>> getNovelListByClass(String classifyId,
      {String? bookStatus,
      String? wordCountMin,
      String? wordCountMax,
      String? sort}) async {
    const path = 'book/bookByCategory';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(
        path,
        body: {
          "catId": classifyId,
          'bookStatus': bookStatus,
          'wordCountMin': wordCountMin,
          'wordCountMax': wordCountMax,
          'sort': sort
        },
        type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<List<Chapter>> getChapterList(String novelId) async {
    const path = 'book/queryIndexList';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(
        path,
        body: {"bookId": novelId.toString(), 'curr': '1', 'limit': '99999999'},
        type);
    final chapterList = response.data['list']
        .map<Chapter>((e) => ChapterModel.fromJson(e).toEntity())
        .toList();

    return chapterList;
  }

  @override
  Future<Chapter> getChapterContent(String novelId, String catalogue) async {
    const path = 'book/queryBookContent';
    RequestType type = RequestType.get;
    final response = await client.invokeHttp(
        path, body: {"bookId": novelId, "bookIndexId": catalogue}, type);
    response.data["index"] = catalogue;
    response.data["id"] = response.data["bookIndex"]['id'];
    response.data["bookId"] = response.data["book"]['id'];
    response.data["indexName"] = response.data["bookIndex"]['indexName'];
    response.data["lastBookContent"] = response.data["bookContent"]['content'];
    return ChapterModel.fromJson(response.data).toEntity();
  }

  @override
  Future<void> novelRead(String novelId) async {
    const path = 'user/addReadHistory';

    RequestType type = RequestType.post;
    await client.invokeHttp(path, body: {"bookId": novelId}, type);
  }

  @override
  Future<List<Novel>> getBookShelf() async {
    const path = 'user/listBookShelfByPage';

    RequestType type = RequestType.get;
    return ((await client.invokeHttp(path, type)).data["list"] as List)
        .map<Novel>((e) => BookShelfModel.fromJson(e).toEntity())
        .toList();
  }

  @override
  Future<List<Novel>> getReadHistory() async {
    const path = 'user/listReadHistoryByPage';

    RequestType type = RequestType.get;
    return ((await client.invokeHttp(path, type)).data["list"] as List)
        .map<Novel>((e) => BookShelfModel.fromJson(e).toEntity())
        .toList();
  }

  @override
  Future<List<Novel>> getEndBookRank() async {
    const path = 'book/endByPage';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<List<Novel>> getHotRank() async {
    const path = 'book/readByPage';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<List<Classify>> getClassifyList(
      {required WorkDirection workDirection,
      required NovelTagType novelTagType}) async {
    RequestType type = RequestType.get;
    final List<Classify> classifyList = [];
    const path = 'category/selectList';
    classifyList.addAll(((await client.invokeHttp(
                path,
                body: {
                  'workDirection': workDirection.index.toString(),
                  'type': novelTagType.index.toString()
                },
                type))
            .data as List)
        .map<Classify>((e) {
      e['parentId'] = novelTagType.index.toString();
      e['parentName'] = EnumDict.novelTagType[novelTagType];
      return BookClassifyModel.fromJson(e).toEntity();
    }));
    return classifyList;
  }

  @override
  Future<List<Classify>> getHotClassifyList(
      {WorkDirection? workDirection}) async {
    RequestType type = RequestType.get;
    final List<Classify> classifyList = [];
    const path = 'category/hotCategory';
    classifyList.addAll(((await client.invokeHttp(
                path,
                body: {
                  'workDirection': workDirection?.index.toString(),
                },
                type))
            .data as List)
        .map<Classify>((e) {
      e['parentId'] = '-1';
      e['parentName'] = '热门';
      e['name'] = e['name'] + ' ';
      return BookClassifyModel.fromJson(e).toEntity();
    }));
    return classifyList;
  }

  Future<List<Novel>> _searchByPage(body) async {
    const path = 'book/searchByPage';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, body: body, type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<List<Novel>> getRecommendRank() async {
    const path = 'book/recommendByPage';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<List<Novel>> getHighScoreRank() => _searchByPage({"sort": "score"});

  @override
  Future<List<Novel>> getGuessYouLikeRank() async {
    const path = 'book/likeByPage';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<List<Novel>> getHotUpRank() => _searchByPage({"sort": "create_time"});

  @override
  Future<List<Novel>> getNewComeRank() async {
    const path = 'book/newByPage';

    RequestType type = RequestType.get;
    final response = await client.invokeHttp(path, type);
    final pagedDataModel = (response.data["list"] as List)
        .map<Novel>((e) => NovelModel.fromJson(e).toEntity())
        .toList();

    return pagedDataModel;
  }

  @override
  Future<void> addVisitCount(String params) async {
    const path = 'book/addVisitCount';

    RequestType type = RequestType.post;
    await client.invokeHttp(path, body: {'bookId': params}, type);
  }
}
